home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 November / macformat-018.iso / Utility Spectacular / Developer / macgambit-20-compiler-src-p1 / Runtime (.c & .h) / os_mac_eKeys.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-26  |  16.2 KB  |  650 lines  |  [TEXT/KAHL]

  1. /* os_mac_eKeys.c
  2.  * 3May92  e
  3.  */
  4.  
  5. #include "os_mac_eEdit.h"
  6.  
  7. /* extensions to an editor for text files by e
  8.    questions/comments via Internet <e@Flavors.COM> */
  9. /* Copyright © e, 1989,1992. All rights reserved.
  10.     Developed using THINK C 5.0.1 for use with Gambit Scheme.
  11.     This code may be freely distributed as long as this notice remains.
  12.    balance_bwd was written by Marc Feeley.
  13. */
  14.  
  15. #define graphic_char(c) (!(((c)>=0) && ((c)<=32)))
  16.  
  17. static long whsp_fwd_guts( eRec **hE, long offs )
  18.   register char *text = *((**hE).hText);
  19.   register char *p = text + offs;
  20.   register char *end = text + eTeTextLength( hE );
  21.   register char c;
  22.  
  23.   while( p < end )
  24.   { c = *p++;
  25.     if( graphic_char(c) )
  26.     { if( c != ';' )
  27.           return p - text - 1;
  28.       else
  29.         while ( p < end && *p++ != '\r' )  ;
  30.     }
  31.   }
  32.   return end - text;
  33. }
  34.  
  35. static long whsp_fwd( eRec **hE )
  36.   long offs = eTeChPosToOffset( hE, (**hE).selActive ? (**hE).selEnd : (**hE).caretChPos );
  37.   return whsp_fwd_guts( hE, offs );
  38. }
  39.  
  40. static long whsp_bwd( eRec **hE )
  41. {
  42.   long offs = eTeChPosToOffset( hE, (**hE).selActive ? (**hE).selStart : (**hE).caretChPos );
  43.   register char *text = *((**hE).hText);
  44.   register char *p = text + offs - 1;
  45.   register char c;
  46.  
  47.   while( p >= text )
  48.   { if( graphic_char( *p ) )
  49.         return p - text + 1;
  50.     else
  51.       p--;
  52.   }
  53.   return 0;
  54. }
  55.  
  56. long balance_fwd_guts( eRec **hE, long offs, int bal )
  57.   register char *text = *((**hE).hText);
  58.   register char *p = text + offs;
  59.   register char *end = text + eTeTextLength( hE );
  60.   register int b = bal;
  61.   register char c;
  62.  
  63.   while( p < end && !graphic_char(*p) ) p++;
  64.  
  65.   while( p < end )
  66.   { c = *p++;
  67.     if( graphic_char(c) )
  68.       switch (c)
  69.       { case '(':
  70.           b++;
  71.           break;
  72.         case ')':
  73.           b--;
  74.           if (b <= 0) goto scan_done;
  75.           break;
  76.         case ';':
  77.           while ( p < end && *p++ != '\r' )  ;
  78.           break;
  79.         case '"':
  80.         { while (p<end)
  81.           { c = *p++;
  82.               if( c == '"' ) goto breake;
  83.               if( c == '\\' ) p++;
  84.           }
  85.           return -1;
  86.           breake:
  87.           if( b <= 0 ) goto scan_done;
  88.           break;
  89.         }
  90.         case '#':
  91.           if( *p == '\\' ) p += 2;
  92.           break;
  93.         case ',':
  94.           if( *p == '@' ) p++;
  95.           break;
  96.         case '\'':
  97.         case '`':
  98.           break;
  99.         default:
  100.         { while ((p<=end) && graphic_char(c) && (c!='(') && (c!=')') && (c!='"'))
  101.             c = *p++;
  102.           p--;
  103.           if (b <= 0) goto scan_done;
  104.           break;
  105.         }
  106.      }
  107.   }
  108.   return -1;
  109.  
  110.   scan_done:
  111.   return p-text;
  112. }
  113.  
  114. long balance_fwd( eRec **hE, int bal )
  115.   long offs = eTeChPosToOffset( hE, (**hE).selActive ? (**hE).selEnd : (**hE).caretChPos );
  116.   return balance_fwd_guts( hE, offs, bal );
  117. }
  118.  
  119. static long balance_bwd_guts( eRec **hE, long offs, int bal, int prefix )
  120. {
  121.   register char *text = *((**hE).hText);
  122.   register char *p = text + offs;
  123.   register int b = bal;
  124.  
  125.   while ((p>text) && !graphic_char(p[-1])) p--;
  126.  
  127.   while (p>text)
  128.     if ((p>=text+3) && (p[-2]=='\\') && (p[-3]=='#'))
  129.     { p -= 3;
  130.       if (b <= 0) goto scan_prefix;
  131.     }
  132.     else
  133.     { register char c = *--p;
  134.       if (graphic_char(c))
  135.         switch (c)
  136.         { case '(':
  137.             b--;
  138.             if (b <= 0) goto scan_prefix;
  139.             break;
  140.           case ')':
  141.             b++;
  142.             break;
  143.           case '"':
  144.           { while (p>text)
  145.             { register char *q = --p;
  146.               while ((q>text) && (q[-1]=='\\')) q--;
  147.               if ((p-q)&1L)
  148.                 p = q;
  149.               else if (*p=='"')
  150.                 if (b <= 0) goto scan_prefix; else goto brak;
  151.             }
  152.             return -1;
  153.             brak:
  154.             break;
  155.           }
  156.           default:
  157.           { while ((p>=text) && graphic_char(c) &&
  158.                    (c!='(') && (c!=')') && (c!='"'))
  159.               c = *--p;
  160.             p++;
  161.             if (b <= 0) goto scan_prefix;
  162.             break;
  163.           }
  164.       }
  165.   }
  166.   return -1;
  167.  
  168.   scan_prefix:
  169.   if (prefix)
  170.     while (p>text)
  171.     { register char c = *--p;
  172.       if ((c!='\'') && (c!='`') && (c!=',') && (c!='@') && (c!='#'))
  173.       { p++; break; }
  174.     }
  175.   return p-text;
  176. }
  177.  
  178. long balance_bwd( eRec **hE, int bal, int prefix )
  179. {
  180.   long offs = eTeChPosToOffset( hE, (**hE).selActive ? (**hE).selStart : (**hE).caretChPos );
  181.   return balance_bwd_guts( hE, offs, bal, prefix );
  182. }
  183.  
  184. static int rangeBalance( register char *beg, register char *end )
  185. {
  186.     register int n = 0;
  187.     
  188.     while(beg < end)
  189.     {    if (*beg == '(')        n++;
  190.         else if (*beg == ')')    n--;
  191.         beg++;
  192.     }
  193.     return(n);
  194. }
  195.  
  196. /* 23Jul92  e  */
  197.  
  198. extern int check_TEInsert( char *ptr, long len, eRec **hE, int bold );
  199.  
  200. #if 0
  201.  
  202. /* 17Aug92  e  */
  203.  
  204. void eTabCommand( eRec **hE, short modifiers, short style )
  205. { long open_paren;
  206.   long selStart, selEnd, selLen;
  207.   ChPos solcp, eolcp;
  208.   char *p;
  209.   long sol, eol;
  210.   long adj = 0;
  211.   Boolean selActive;
  212.  
  213.   if( ( selActive = (**hE).selActive ) )
  214.   {    selStart = eTeChPosToOffset( hE, (**hE).selStart );
  215.     selEnd   = eTeChPosToOffset( hE, (**hE).selEnd );
  216.     selLen   = selEnd - selStart;
  217.     eTeSetSelect( hE, selStart, selStart );
  218.     solcp = (**hE).selStart;
  219.   }
  220.   else
  221.   {    selStart = eTeChPosToOffset( hE, (**hE).caretChPos );
  222.     selLen = 0;
  223.     solcp = (**hE).caretChPos;
  224.   }
  225.   eolcp.h = solcp.h = 0;    /* start of line */
  226.   eolcp.v = solcp.v + 1;
  227.   eol = eTeChPosToOffset( hE, eolcp );    /* next line */
  228.   sol = eTeChPosToOffset( hE, solcp );    /* this line */
  229.   p = *((**hE).hText) + sol;
  230.   while( ! graphic_char( *p ) && sol < eol && *p != RETURN ) { p++; sol++; solcp.h++; }
  231.   if( sol != selStart ) eTeSetSelect( hE, sol, sol );
  232.   if( sol < selStart )  adj = selStart - sol;
  233.   
  234.   open_paren = balance_bwd( hE, 0, 1 );
  235.   eolcp = eTeOffsetToChPos( hE, open_paren );
  236.   if( solcp.h > eolcp.h )
  237.   { eolcp.v = solcp.v;
  238.     eol = eTeChPosToOffset( hE, eolcp );
  239.     eTeSetSelect( hE, eol, eol );
  240.     eTeKillTo( hE, solcp );
  241.   }
  242.   else while (solcp.h < eolcp.h)
  243.   { long len = (eolcp.h - solcp.h < 80) ? eolcp.h - solcp.h : 80;
  244.     if (check_TEInsert( "                                                                                ",
  245.                         len, hE, style )) goto err;
  246.     solcp.h += len;
  247.   }
  248.   err:
  249.   if( sol < selStart || selActive )
  250.   { selStart = eTeChPosToOffset( hE, (**hE).caretChPos ) + adj;
  251.     eTeSetSelect( hE, selStart, selStart + selLen );
  252.   }
  253.   eTeShowCaret( hE );
  254. }
  255.  
  256. #else
  257.  
  258. /* 14Oct92  e  */
  259.  
  260. static char dncase( char c )
  261. { if( c >= 'A' &&  c <= 'Z' ) return c + 0x20;
  262.   else return c;
  263. }
  264.  
  265. static Boolean eq_subfs( char *p, char *q )
  266. { char c;
  267.   while( c = *p++ )
  268.     if( c != dncase( *q++ ) )
  269.       return FALSE;
  270.   c = *q;
  271.   return( ( graphic_char(c) && c != '(' && c != '"' ) ? FALSE : TRUE );
  272. }
  273.  
  274. /* subforms of forms whose car is in this table are indented specially...
  275.   call the subform to be indented "the target":
  276.   if there are more than cnt subforms between the car and the target,
  277.     then the last subform before the target determines the postion of the target,
  278.   otherwise the target is indented one more space than the car
  279. */ 
  280.  
  281. struct _spec_subfs { char *str; char cnt; };
  282.  
  283. static struct _spec_subfs spec_subfs_data[] =
  284.     { { "if", 1 },
  285.       { "do", 2 },
  286.       { "do*", 2 },
  287.       { "let", 18 },    /* special case for named let */
  288.       { "let*", 1 },
  289.       { "case", 1 },
  290.       { "begin", 0 },
  291.       { "lambda", 1 },
  292.       { "letrec", 1 },
  293.       { "define", 1 },
  294.       { "##declare", 0 },
  295.       { "##define-macro", 1 },
  296.       { "", -1 }
  297.     };
  298.  
  299. static long spec_subfs( char *p )
  300. { char c;
  301.   long res = -1;
  302.   struct _spec_subfs *s = spec_subfs_data;
  303.   if( (c = dncase(*p)) >= 'a' && c <= 'z' )
  304.     while( (res = (*s).cnt) >= 0 )
  305.       if( eq_subfs( (*s).str, p ) )
  306.         break;
  307.       else
  308.         s++;
  309.   return res;
  310. }
  311.  
  312. void eTabCommand( eRec **hE, short modifiers, short style )
  313. { long open_paren, upen_paren;
  314.   long selStart, selEnd, selLen;
  315.   ChPos solcp, eolcp;
  316.   char *p;
  317.   long sol, eol;
  318.   long adj = 0;
  319.   Boolean selActive;
  320.   
  321.   if( ( selActive = (**hE).selActive ) )
  322.   {    selStart = eTeChPosToOffset( hE, (**hE).selStart );
  323.     selEnd   = eTeChPosToOffset( hE, (**hE).selEnd );
  324.     selLen   = selEnd - selStart;
  325.     eTeSetSelect( hE, selStart, selStart );
  326.     solcp = (**hE).selStart;
  327.   }
  328.   else
  329.   {    selStart = eTeChPosToOffset( hE, (**hE).caretChPos );
  330.     selLen = 0;
  331.     solcp = (**hE).caretChPos;
  332.   }
  333.   eolcp.h = solcp.h = 0;    /* start of line */
  334.   eolcp.v = solcp.v + 1;
  335.   eol = eTeChPosToOffset( hE, eolcp );    /* next line */
  336.   sol = eTeChPosToOffset( hE, solcp );    /* this line */
  337.   p = *((**hE).hText) + sol;
  338.   while( ! graphic_char( *p ) && sol < eol && *p != RETURN ) { p++; sol++; solcp.h++; }
  339.   if( sol != selStart ) eTeSetSelect( hE, sol, sol );
  340.   if( sol < selStart )  adj = selStart - sol;
  341.   
  342.   open_paren = balance_bwd_guts( hE, sol, 0, 1 );
  343.   /*  14Oct92  e  */
  344.   if( open_paren > 0 )
  345.   { upen_paren = balance_bwd_guts( hE, sol, 1, 1 );
  346.     if( upen_paren < 0 )
  347.     { /* a toplevel form should be at column zero !? */
  348.       eolcp.h = 0;
  349.       goto justdotab;
  350.     }
  351.     else
  352.     { long rover, prevr, first;
  353.       long count = 0;
  354.       char *text = *((**hE).hText);
  355.       p = text + upen_paren;
  356.       while( *p != '(' ) p++;    /* there must be a '(' since upen_paren >= 0 */ 
  357.       upen_paren = p - text;    /* the offset of the '(' */
  358.       prevr = upen_paren + 1;
  359.       rover = first = whsp_fwd_guts( hE, prevr );
  360.       while( rover > 0 && rover < open_paren )
  361.       { prevr = rover;
  362.           count++;
  363.         rover = balance_fwd_guts( hE, rover, 0 );
  364.         if( rover > 0 ) rover = whsp_fwd_guts( hE, rover );
  365.       }
  366.       /* now...
  367.         upen_paren = start of enclosing form
  368.         open_paren = start of preceeding form
  369.         first = first sub-form of enclosing form
  370.         prevr = last sub-form of enclosing form <= open_paren, or upen_paren+1 if none
  371.         rover = last sub-form of enclosing form >= open_paren, or -1 if none
  372.         count = position of rover in subforms of enclosing form
  373.       */ /* this catches subforms inside comments... */
  374.       if( rover != open_paren ) { open_paren = prevr; count--; }
  375.       /* this handles special indentation for special forms... */
  376.       if( first < sol
  377.           && (rover = spec_subfs( text + first ) ) >= 0
  378.           && ( count == 0 || count == rover || ( rover > 15 && count <= (rover&15)) ) )
  379.       { eolcp = eTeOffsetToChPos( hE, first );
  380.           eolcp.h += 1;
  381.           goto justdotab;
  382.       }
  383.     }
  384.   }
  385.   /* */
  386.   eolcp = eTeOffsetToChPos( hE, open_paren );
  387. justdotab:
  388.   if( solcp.h > eolcp.h )
  389.   { eolcp.v = solcp.v;
  390.     eol = eTeChPosToOffset( hE, eolcp );
  391.     /* 27Jan93  e  -- this mungs the scrap...
  392.     eTeSetSelect( hE, eol, eol );
  393.     eTeKillTo( hE, solcp );
  394.     instead... */
  395.     eTeSetSelect( hE, eol, sol );
  396.     eTeDelete( hE );
  397.   }
  398.   else while (solcp.h < eolcp.h)
  399.   { long len = (eolcp.h - solcp.h < 80) ? eolcp.h - solcp.h : 80;
  400.     if (check_TEInsert( "                                                                                ",
  401.                         len, hE, style )) goto err;
  402.     solcp.h += len;
  403.   }
  404.   err:
  405.   if( sol < selStart || selActive )
  406.   { selStart = eTeChPosToOffset( hE, (**hE).caretChPos ) + adj;
  407.     eTeSetSelect( hE, selStart, selStart + selLen );
  408.   }
  409.   eTeShowCaret( hE );
  410. }
  411.  
  412. #endif
  413.  
  414. #define mCheck(n, ch) ((rover[n] == ch) && (n >= 0) && (n < teLength))
  415.  
  416. void eEditCommand( eRec **hE, char ch, short modifiers, short style )
  417. {
  418.     register char *rover;
  419.     register long needLeft, needRight;
  420.     long selStart, selEnd, teLength;
  421.     short wanted;    /* -1 at start, 0 range, 1 at end */
  422.     Boolean selActive;
  423.     short optioned = modifiers & optionKey;
  424.     short shifted  = modifiers & shiftKey;
  425.     
  426.     ch += 0x40;    /* undo control key */
  427.     modifiers &= ~controlKey;
  428.     
  429.     if( ( selActive = (**hE).selActive ) )
  430.     {    selStart = eTeChPosToOffset( hE, (**hE).selStart );
  431.         selEnd =   eTeChPosToOffset( hE, (**hE).selEnd );
  432.     }
  433.     else
  434.     {    selEnd = selStart = eTeChPosToOffset( hE, (**hE).caretChPos );
  435.     }
  436.     teLength = eTeTextLength( hE );
  437.     
  438.     rover = (char *)*(**hE).hText;
  439.     wanted = 0;                        /* always range; someday use mark */
  440.     needLeft = needRight = 0;
  441.  
  442.     switch( ch )
  443.     {
  444.         case 'T':            /* Transpose */        /* 22Jul92  e  */
  445.         case 't':
  446.         case '†':    /* option-t */
  447.         case 'ˇ':    /* option-shift-t */
  448.             if( selActive )
  449.               SysBeep(6);
  450.             else if( optioned )
  451.             { needLeft  = balance_bwd( hE, 0, 1 );
  452.               needRight = balance_fwd( hE, 0 );
  453.               if( needLeft >= 0 && needRight >= 0 )
  454.                 eTeTranspose( hE, needLeft, whsp_bwd( hE ), whsp_fwd( hE ), needRight );
  455.               else
  456.                 SysBeep(6); /* can't be done! */
  457.             }
  458.             else
  459.               eTeTranspose( hE, selStart - 1, selStart, selStart, selStart + 1 );
  460.             return;
  461.  
  462.         case 'K':            /* Kill */
  463.         case 'k':
  464.         case '':    /* option-k */
  465.         case '˚':    /* option-shift-k */
  466.             if( ! selActive && optioned )
  467.             { /* c-m-k (del-fwd-sexp) */
  468.               selEnd = balance_fwd( hE, 0 );
  469.               if( selEnd >= 0 )
  470.               { eTeKillTo( hE, eTeOffsetToChPos( hE, selEnd ) );
  471.               }
  472.               else SysBeep( 3 );
  473.             }
  474.             else /* Kill line */
  475.               eTeKey( hE, 0x7f, KeyDel, optionKey, style);
  476.             return;
  477.  
  478.         case 'D':            /* Delete */
  479.         case 'd':
  480.             eTeKey( hE, 0x7f, KeyDel, 0, style);
  481.             return;
  482.  
  483.         case 'O':            /* Open line */
  484.         case 'o':
  485.         case 'ø':    /* option-o */
  486.         case 'Ø':    /* option-shift-o */
  487.             if( selActive )
  488.                 eTeSetSelect( hE, selStart, selStart );
  489.             eTeKey( hE, '\r', 0, 0, style);
  490.             eTeSetSelect( hE, selStart, selStart );
  491.             return;
  492.  
  493.         case 'A':
  494.         case 'a':
  495.         case 'å':    /* option-a */
  496.         case 'Å':    /* option-shift-a */
  497.             if( optioned )
  498.             {    wanted = shifted ? 0 : -1;
  499.                 needLeft = 2;
  500.                 /* needRight = 2; */
  501.                 break;
  502.             }
  503.             eTeKey( hE, LEFT_ARROW, 0, modifiers | cmdKey, style );
  504.             return;
  505.  
  506.         case 'E':
  507.         case 'e':
  508.                     /* option-e is a dead key */
  509.         case '´':    /* option-shift-e */
  510.             if( optioned )
  511.             {    wanted = shifted ? 0 : 1;
  512.                 /* needLeft = 2; */
  513.                 needRight = 2;
  514.                 break;
  515.             }
  516.             eTeKey( hE, RIGHT_ARROW, 0, modifiers | cmdKey, style );
  517.             return;
  518.  
  519.         case 'P':                            /* Previous */
  520.         case 'p':
  521.         case 'π':    /* option-p */
  522.         case '∏':    /* option-shift-p */
  523.             eTeKey( hE, UP_ARROW, 0, modifiers, style );
  524.             return;
  525.  
  526.         case 'N':                            /* Next */
  527.         case 'n':
  528.                     /* option-n is a dead key */
  529.         case '˜':    /* option-shift-n */
  530.             eTeKey( hE, DOWN_ARROW, 0, modifiers, style );
  531.             return;
  532.  
  533.         case 'M':                            /* Match (Balance) */
  534.         case 'm':
  535.         case 'µ':    /* option-m */
  536.         case 'Â':    /* option-shift-m */
  537.             if( ! selActive )
  538.             {    /* too smart?  22Jul92  e
  539.                 if( mCheck( selStart, '(' ) )
  540.                 {    selEnd = selStart + 1;
  541.                     needLeft = 0;
  542.                     needRight = 1;
  543.                 }
  544.                 else if( mCheck( selStart - 1, ')' ) )
  545.                 {    selStart = selEnd - 1;
  546.                     needLeft = 1;
  547.                     needRight = 0;
  548.                 }
  549.                 else
  550.                 {    needLeft = 1;
  551.                     needRight = 1;
  552.                 }
  553.                 */
  554.                 needLeft = 2;
  555.                 needRight = 2;
  556.             }
  557.             else
  558.             {    needRight = rangeBalance( &rover[selStart], &rover[selEnd] );
  559.                 /* too smart?  22Jul92  e
  560.                 if( needRight == 0 )
  561.                 {    needLeft = 1;
  562.                     needRight = 1;
  563.                 }
  564.                 else if( needRight < 0 )
  565.                 {    needLeft = -needRight;
  566.                     if( mCheck(selEnd - 1, ')' ) )
  567.                         needRight = 0;
  568.                     else
  569.                     {    needRight = 1;
  570.                         needLeft += 1;
  571.                     }
  572.                 }
  573.                 else
  574.                 {    if( mCheck( selStart, '(' ) )
  575.                         needLeft = 0;
  576.                     else
  577.                     {    needLeft = 1;
  578.                         needRight += 1;
  579.                     }
  580.                 }
  581.                 */
  582.                 if( needRight == 0 )
  583.                 {    needLeft = 2;
  584.                     needRight = 2;
  585.                 }
  586.                 else if( needRight < 0 )
  587.                 {    needLeft = -needRight;
  588.                     needRight = 2;
  589.                     needLeft += 2;
  590.                 }
  591.                 else
  592.                 {    needLeft = 2;
  593.                     needRight += 2;
  594.                 }
  595.             }
  596.             break;
  597.  
  598.         case 'ƒ':    /* option f */                /* Forward */
  599.         case 'f':
  600.         case 'Ï':    /* option shift f */
  601.         case 'F':
  602.             wanted = shifted ? 0 : 1;
  603.             if( ! selActive || shifted )
  604.             {    if( optioned ) needRight = 1;
  605.                 else
  606.                 {    eTeKey( hE, RIGHT_ARROW, 0, modifiers, style );
  607.                     return;
  608.                 }
  609.             }
  610.             /* else    selection range case automatic */
  611.             break;
  612.  
  613.         case '∫':    /* option b */                /* Back */
  614.         case 'b':
  615.         case 'ı':    /* option shift b */
  616.         case 'B':
  617.             wanted = shifted ? 0 : -1;
  618.             if( ! selActive || shifted )
  619.             {    if( optioned ) needLeft = 1;
  620.                 else
  621.                 {    eTeKey( hE, LEFT_ARROW, 0, modifiers, style );
  622.                     return;
  623.                 }
  624.             }
  625.             /* else    selection range case automatic */
  626.             break;
  627.  
  628.         default:
  629.             return;
  630.     }
  631.     if( needRight != 0 )
  632.     {     selEnd   = balance_fwd( hE, needRight - 1 );
  633.         if( selEnd   < 0 ) { SysBeep(6); return; } /* can't be done! */
  634.     }
  635.     if( needLeft  != 0 )
  636.     {     selStart = balance_bwd( hE, needLeft  - 1, 1 );
  637.         if( selStart < 0 ) { SysBeep(6); return; } /* can't be done! */
  638.     }
  639.     eTeSetSelect( hE,
  640.                   (wanted ==  1) ? selEnd : selStart,
  641.                   (wanted == -1) ? selStart : selEnd  );
  642.     eTeShowCaret( hE );
  643. }
  644.  
  645. /* end of os_mac_eKeys.c */
  646.